package com.lgc.webtest.configuration;

import org.springframework.amqp.core.*;
import org.springframework.amqp.rabbit.connection.CachingConnectionFactory;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;


/**
 * RabbitConfig队列配置
 * 一个发送者，N个接收者或者N个发送者和N个接收者,接收端会均匀接收到消息
 */
//@Configuration
public class RabbitMQConfig {

    public final static String QUEUE_NAME = "test-queue1";
    public final static String QUEUE_NAME2 = "test-queue2";

    //***根据Binding指定的Routing key,将符合key的消息发送的Binding的queue.
    //直接交换器，工作方式类似于单播，Exchange会将消息发送完全匹配ROUTING_KEY的Queue
    public final static String DIRECT_EXCHANGE_NAME = "test-exchange.direct";
//    public final static String DIRECT_EXCHANGE_NAME2 = "test-exchange.direct";
    //工作方式类似于组播，Exchange会将消息转发和ROUTING_KEY匹配模式相同的所有队列,
    //符号#匹配一个或多个字符,符号*匹配一个词,因此audit.#可以匹配上audit.aa.bba,而audit.*仅可匹配audit.air
    public final static String TOPIC_EXCHANGE_NAME = "test-exchange.topic";
    //广播是式交换器，不管消息的ROUTING_KEY设置为什么，Exchange都会将消息转发给所有绑定的Queue
    public final static String FANOUT_EXCHANGE_NAME = "amq.fanout";
    public final static String ROUTING_KEY = "test-routing-key";
    public final static String ROUTING_KEY2 = "test-routing-key2";

    @Value("${spring.rabbitmq.host}")
    private String host;

    @Value("${spring.rabbitmq.port}")
    private String port;

    @Value("${spring.rabbitmq.username}")
    private String username;

    @Value("${spring.rabbitmq.password}")
    private String password;

    @Value("${spring.rabbitmq.publisher-confirms}")
    private Boolean publisherConfirms;

    @Value("${spring.rabbitmq.virtual-host}")
    private String virtualHost;

    // 创建队列
    @Bean("queue1")
    public Queue helloQueue()
    {
        return new Queue(QUEUE_NAME,true);
    } //第二个参数druable是否持久化
    @Bean("queue2")
    public Queue helloQueue2()
    {
        return new Queue(QUEUE_NAME2);
    }

    // 创建一个 direct 类型的交换器
//    @Bean
//    public DirectExchange exchange() {
//        return new DirectExchange(DIRECT_EXCHANGE_NAME,true,false);
//    }
//
//
//    // 使用路由键（routingKey）把队列（Queue）绑定到交换器（Exchange）
//    @Bean
//    public Binding binding(@Qualifier("queue1") Queue queue,@Qualifier("exchange") DirectExchange exchange) {
//        return BindingBuilder.bind(queue).to(exchange).with(ROUTING_KEY);
//    }
//    @Bean
//    public Binding binding2(@Qualifier("queue2") Queue queue,@Qualifier("exchange") DirectExchange exchange) {
//        return BindingBuilder.bind(queue).to(exchange).with(ROUTING_KEY2);
//    }

    //创建工厂连接
    @Bean
    public ConnectionFactory connectionFactory(){
        CachingConnectionFactory connectionFactory = new CachingConnectionFactory();
        connectionFactory.setAddresses(this.host+":"+this.port);
        connectionFactory.setUsername(this.username);
        connectionFactory.setPassword(this.password);
        connectionFactory.setVirtualHost(this.virtualHost);
        connectionFactory.setPublisherConfirms(this.publisherConfirms); //必须要设置,才能进行消息的回调
        return connectionFactory;
    }

    /*如果需要在生产者需要消息发送后的回调，需要对rabbitTemplate设置ConfirmCallback对象，
    由于不同的生产者需要对应不同的ConfirmCallback，如果rabbitTemplate设置为单例bean，
    则所有的rabbitTemplate 实际的ConfirmCallback为最后一次申明的ConfirmCallback。*/

    //rabbitmq的模板配置
    @Bean
    @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
    //必须是prototype类型,** 因为要设置回调类，所以应是prototype类型，如果是singleton类型，则回调类为最后一次设置
    public RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory) {
        return new RabbitTemplate(connectionFactory);
    }
}
